package com.pay.ioopos.support.scan;

import android.util.Log;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.OnLifecycleEvent;

import com.pay.ioopos.ScanListener;
import com.pay.ioopos.support.utils.HEX;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android_serialport_api.SerialPort;

public class ScanIcCard implements ScanCase {
    private static final String TAG = ScanIcCard.class.getSimpleName();
    private ExecutorService service = Executors.newFixedThreadPool(1);
    private boolean isScaned = false;
    private ScanListener listener;
    private String devPath;
    private int baudrate;

    public ScanIcCard() {
        this("/dev/ttyMT1", 9600);
    }

    public ScanIcCard(String devPath, int baudrate) {
        this.devPath = devPath;
        this.baudrate = baudrate;
    }

    @Override
    public void bindToLifecycle(LifecycleOwner lifecycleOwner) {
        lifecycleOwner.getLifecycle().addObserver(createLifecycleObserver());
    }

    @Override
    public void setScanListener(ScanListener listener) {
        this.listener = listener;
    }

    private LifecycleObserver createLifecycleObserver() {
        ScanIcCard that = this;
        return new LifecycleObserver() {
            @OnLifecycleEvent(Lifecycle.Event.ON_START)
            public void onStart(LifecycleOwner lifecycleOwner) {
                service.submit(that::reading);
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
            public void onStop(LifecycleOwner lifecycleOwner) {
                service.shutdownNow();
            }

            @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
            public void onDestroy(LifecycleOwner lifecycleOwner) {
                lifecycleOwner.getLifecycle().removeObserver(this);
            }
        };
    }

    private void reading() {
        byte[] buffer = new byte[512];
        try(SerialPort serialPort = new SerialPort(new File(devPath), baudrate, 0);
            InputStream inputStream = serialPort.getInputStream()) {
            while(!Thread.interrupted()) {
                int len = inputStream.read(buffer);
                if (len > 0) {
                    byte[] data = new byte[len];
                    for (int i = 0; i < len; i++) {
                        data[i] = buffer[i];
                    }
                    Log.d(TAG, "接收数据: " + HEX.toHexString(data).toUpperCase());
                    onReceive(data);
                } else {
                    Log.d(TAG, "接收数据:（空）");
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "接收数据：", e);
        }
    }

    private void onReceive(byte[] data) {
         IcReceiveCmd cmd;
        try {
            cmd = IcReceiveCmd.parse(data);
        } catch (Exception e) {
            listener.onError("解析数据：" + e.getMessage());
            return;
        }
        if (!cmd.isSuccess()) {
            listener.onError(cmd.getDescr());
            return;
        }
        final byte[] content = cmd.getData();
        Log.d(TAG, cmd.getDescr()  + (null == content ? "": "：" + HEX.toHexString(content).toUpperCase()));
        if (!isScaned) {
            isScaned = true;
            isScaned = listener.onScan(new String(content));
        }
    }

    private void send(byte[] data) {
        Log.d(TAG, "发送数据: " + HEX.toHexString(data).toUpperCase());
        try (SerialPort serialPort = new SerialPort(new File(devPath), baudrate, 0);
             OutputStream outputStream = serialPort.getOutputStream())  {
            outputStream.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
